package cn.dazhou.networkdemo

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.telephony.TelephonyManager
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import cn.dazhou.networkdemo.databinding.ActivityPreferredNetworkTypeBinding
import timber.log.Timber
import java.util.TreeMap
import kotlin.concurrent.thread

class PreferredNetworkTypeActivity : AppCompatActivity() {

    private val binding by lazy { ActivityPreferredNetworkTypeBinding.inflate(layoutInflater) }
    private val tm by lazy { getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        updateCurrentNetworkType()
        // tm.setPreferredNetworkTypeToGlobal()
        printAllNetworkMode()
        binding.lteOnly.setOnClickListener { setPreferredNetworkType(tm.NETWORK_MODE_LTE_ONLY) }
        binding.nrOnly.setOnClickListener { setPreferredNetworkType(tm.NETWORK_MODE_NR_ONLY) }
        binding.lteNrOnly.setOnClickListener { setPreferredNetworkType(tm.NETWORK_MODE_NR_LTE) }
        binding.ltePref.setOnClickListener { setPreferredNetworkType(tm.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA) }
        binding.nrPref.setOnClickListener { setPreferredNetworkType(tm.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA) }
    }

    fun setPreferredNetworkType(networkType: Int) {
        binding.loading.visibility = View.VISIBLE
        thread {
            // 当切换网络的时候，比如从仅5G优选切换到4G优先，此时是不允许使用5G了，则切换到4G就会花比较多的时间
            // 如果网络类型变了，但是网络没变，这样的切换就很快，比如从5G优先切换到仅5G就很快，或者从仅4G切换到4G优先也很快。
            tm.setPreferredNetworkType(tm.getSubId(), networkType)
            runOnUiThread {
                updateCurrentNetworkType()
                binding.loading.visibility = View.GONE
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateCurrentNetworkType() {
        binding.textView.text = "当前首选网络类型：${getNetworkTypeName(tm.getPreferredNetworkType(tm.getSubId()))}"
    }

    /** 值为11，仅4G */
    val TelephonyManager.NETWORK_MODE_LTE_ONLY: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_LTE_ONLY")
            return field.getInt(this)
        }

    /** 值为23，仅5G */
    val TelephonyManager.NETWORK_MODE_NR_ONLY: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_NR_ONLY")
            return field.getInt(this)
        }

    /** 值为24，仅5G/4G */
    val TelephonyManager.NETWORK_MODE_NR_LTE: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_NR_LTE")
            return field.getInt(this)
        }

    /** 值为7，最广的网络类型，包含5G、4G、3G、2G */
    val TelephonyManager.NETWORK_MODE_GLOBAL: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_GLOBAL")
            return field.getInt(this)
        }


    /** 值为22，4G优先，包含4G、3G、2G */
    val TelephonyManager.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA")
            return field.getInt(this)
        }


    /** 值为33，5G优先，最广的网络类型，包含5G、4G、3G、2G */
    val TelephonyManager.NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA: Int
        get() {
            val field = TelephonyManager::class.java.getField("NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA")
            return field.getInt(this)
        }
    @SuppressLint("SoonBlockedPrivateApi")
    fun TelephonyManager.getSubId(): Int {
        // 注：当没有系统签名时，它竟然报这个异常：java.lang.NoSuchMethodException: android.telephony.TelephonyManager.getSubId []
        val getSubIdMethod = TelephonyManager::class.java.getDeclaredMethod("getSubId").also { it.isAccessible = true }
        val subId = getSubIdMethod.invoke(this) as Int
        return subId
    }

    fun TelephonyManager.getPreferredNetworkType(subId: Int): Int {
        val getPreferredNetworkTypeMethod = TelephonyManager::class.java.getMethod("getPreferredNetworkType", Int::class.java)
        val preferredNetworkType = getPreferredNetworkTypeMethod.invoke(this, subId) as Int
        return preferredNetworkType
    }

    fun TelephonyManager.setPreferredNetworkType(subId: Int, networkType: Int) {
        val setPreferredNetworkTypeMethod = TelephonyManager::class.java.getMethod("setPreferredNetworkType", Int::class.java, Int::class.java)
        setPreferredNetworkTypeMethod.invoke(this, subId, networkType)
    }

    fun getAllNetworkMode(): TreeMap<Int, String> {
        if (map.isNotEmpty()) {
            return map
        }

        TelephonyManager::class.java.fields.forEach { field ->
            val fieldName = field.name
            if (fieldName.startsWith("NETWORK_MODE_")) {
                val fieldValue = field.getInt(null)
                map[fieldValue] = fieldName // 把value当key，是让其对值排序
            }
        }
        return map
    }

    private val map = TreeMap<Int, String>()

    fun printAllNetworkMode() {
        val map = getAllNetworkMode()
        for ((key, value) in map) {
            Timber.i("$value=$key")
        }
    }

    fun getNetworkTypeName(networkType: Int): String {
        val map = getAllNetworkMode()
        return map[networkType] ?: "未知"
    }

}